package com.iot08.api.utils.applepay;


import com.iot08.apple.pay.client.APIException;
import com.iot08.apple.pay.client.AppStoreServerAPIClient;
import com.iot08.apple.pay.model.*;
import com.iot08.apple.pay.verification.SignedDataVerifier;
import com.iot08.apple.pay.verification.VerificationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author cwj
 * @description
 * @date 2025/1/11 18:21
 **/
@Slf4j
@Component
public class ApplePayUtil {


    @Value("${apple.pay.key.path}")
    private String keyPath;

    @Value("${apple.pay.key.id}")
    private String keyId;

    @Value("${apple.pay.bundle.id}")
    private String bundleId;

    @Value("${apple.pay.issure.id}")
    private String issureId;

    @Value("${apple.pay.sand.env}")
    private boolean isSandEnv;

    @Value("${apple.pay.root.ca1}")
    private String rootCa1;

    @Value("${apple.pay.root.ca2}")
    private String rootCa2;

    @Value("${apple.pay.root.ca3}")
    private String rootCa3;

    @Value("${apple.pay.root.ca4}")
    private String rootCa4;

    @Value("${apple.pay.app.apple.id}")
    private Long appAppleId;

    //私钥Key
    private String encodedKey;

    //公钥证书
    private Set<InputStream> rootAcs = new HashSet<>();

    private Set<InputStream> rootAcs2 = new HashSet<>();
    
    private SignedDataVerifier signedDataVerifier;

    private SignedDataVerifier signedDataVerifierVer;

    private AppStoreServerAPIClient appStoreServerAPIClient;

    /**
     * @description 初始化，读取Apple支付的配置文件
     * @author cwj
     * @param []
     * @return void
     * @date @time 2025/1/13 9:51
     **/
    @PostConstruct
    public void init() throws IOException {
        //读取
        byte[] keyBytes = Files.readAllBytes(Paths.get(keyPath));
        //将私钥内容转换为字符串并去掉头尾的标识符
        encodedKey = new String(keyBytes)
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s+", ""); // 删除所有空格和换行
        rootAcs.add(Files.newInputStream(Paths.get(rootCa1)));
        rootAcs.add(Files.newInputStream(Paths.get(rootCa2)));
        rootAcs.add(Files.newInputStream(Paths.get(rootCa3)));
        rootAcs.add(Files.newInputStream(Paths.get(rootCa4)));
        rootAcs2.add(Files.newInputStream(Paths.get(rootCa1)));
        rootAcs2.add(Files.newInputStream(Paths.get(rootCa2)));
        rootAcs2.add(Files.newInputStream(Paths.get(rootCa3)));
        rootAcs2.add(Files.newInputStream(Paths.get(rootCa4)));
        signedDataVerifier = createSignedDataVerifier();
        signedDataVerifierVer = createSignedDataVerifier(true);
        appStoreServerAPIClient = new AppStoreServerAPIClient(encodedKey,keyId,issureId,bundleId, isSandEnv? Environment.SANDBOX:Environment.PRODUCTION);
    }


    /**
     * @description 查询用户订单信息
     * @author cwj
     * @param [transactionId]
     * @return com.apple.itunes.storekit.model.TransactionInfoResponse
     * @date @time 2025/1/13 9:36
     **/
    public JWSTransactionDecodedPayload queryAppleTransactionInfo(String transactionId)  {
        try
        {
            if(StringUtils.isNotEmpty(transactionId)){
                if(ObjectUtils.isEmpty(appStoreServerAPIClient)){
                    appStoreServerAPIClient = new AppStoreServerAPIClient(encodedKey,keyId,issureId,bundleId, isSandEnv? Environment.SANDBOX:Environment.PRODUCTION);
                }
                if(ObjectUtils.isEmpty(signedDataVerifier)){
                    signedDataVerifier = createSignedDataVerifier();
                }
                //解析订单数据
                return getJwsTransactionDecodedPayload(appStoreServerAPIClient,transactionId,signedDataVerifier);
            }
        } catch (APIException | IOException | VerificationException ae){
            log.error("查询订单信息出现异常，异常信息为：{}",ae.getMessage());
            try{
                log.info("沙箱环境查询支付订单信息......");
                AppStoreServerAPIClient appStoreServerAPIClientSand = new AppStoreServerAPIClient(encodedKey,keyId,issureId,bundleId, Environment.SANDBOX);
                if(ObjectUtils.isEmpty(signedDataVerifierVer)){
                    signedDataVerifierVer = createSignedDataVerifier(true);
                }
                return getJwsTransactionDecodedPayload(appStoreServerAPIClientSand,transactionId,signedDataVerifierVer);
            }catch (APIException | IOException | VerificationException e){
                log.error("沙箱环境查询订单信息出现异常，异常信息为：{}",e.getMessage());
                return null;
            }
        }
        return null;
    }

    public List<JWSTransactionDecodedPayload> queryAppleHistoryTransactionInfo(String transactionId,TransactionHistoryRequest transactionHistoryRequest) {
        try
        {
            if(StringUtils.isNotEmpty(transactionId)){
                if(ObjectUtils.isEmpty(appStoreServerAPIClient)){
                    appStoreServerAPIClient = new AppStoreServerAPIClient(encodedKey,keyId,issureId,bundleId, isSandEnv? Environment.SANDBOX:Environment.PRODUCTION);
                }
                if(ObjectUtils.isEmpty(signedDataVerifier)){
                    signedDataVerifier = createSignedDataVerifier();
                }
                //解析订单数据
                return getHistoryJwsTransactionDecodedPayload(appStoreServerAPIClient,transactionId,signedDataVerifier,transactionHistoryRequest);
            }
        } catch (APIException | IOException | VerificationException ae){
            log.error("查询订单信息出现异常，异常信息为：{}",ae.getMessage());
            try{
                log.info("沙箱环境查询支付订单信息......");
                AppStoreServerAPIClient appStoreServerAPIClientSand = new AppStoreServerAPIClient(encodedKey,keyId,issureId,bundleId, Environment.SANDBOX);
                if(ObjectUtils.isEmpty(signedDataVerifierVer)){
                    signedDataVerifierVer = createSignedDataVerifier(true);
                }
                return getHistoryJwsTransactionDecodedPayload(appStoreServerAPIClientSand,transactionId,signedDataVerifierVer,transactionHistoryRequest);
            }catch (APIException | IOException | VerificationException e){
                log.error("沙箱环境查询订单信息出现异常，异常信息为：{}",e.getMessage());
                return null;
            }
        }
        return null;
    }

    /**
     * @description 解析订单数据
     * @author cwj
     * @param [transactionId]
     * @return com.iot08.apple.pay.model.JWSTransactionDecodedPayload
     * @date @time 2025/2/5 9:29
     **/
    private JWSTransactionDecodedPayload getJwsTransactionDecodedPayload(AppStoreServerAPIClient appleClient,String transactionId,SignedDataVerifier sdv) throws APIException, IOException, VerificationException {
        TransactionInfoResponse transactionInfo = appleClient.getTransactionInfo(transactionId);
        log.info("查询到的苹果订单信息为：{}",transactionInfo);
        if(ObjectUtils.isNotEmpty(transactionInfo)){
            JWSTransactionDecodedPayload transactionDecodedPayload = sdv.verifyAndDecodeTransaction(transactionInfo.getSignedTransactionInfo());
            log.info("验签解码后的数据为：{}",transactionDecodedPayload);
            return transactionDecodedPayload;
        } else {
            return null;
        }
    }


    /**
     * @description 查询历史订单信息
     * @author cwj
     * @param [appleClient, transactionId, sdv]
     * @return java.util.List<com.iot08.apple.pay.model.JWSTransactionDecodedPayload>
     * @date @time 2025/2/17 11:27
     **/
    private List<JWSTransactionDecodedPayload> getHistoryJwsTransactionDecodedPayload(AppStoreServerAPIClient appleClient,String transactionId,SignedDataVerifier sdv,TransactionHistoryRequest transactionHistoryRequest) throws APIException, IOException, VerificationException {
        List<JWSTransactionDecodedPayload>  transactionDecodedPayloads = new ArrayList<>();
        boolean hasMore = false;
        String revision =null;
        do{
            HistoryResponse historyResponse = appleClient.getTransactionHistory(transactionId,revision,transactionHistoryRequest);
            log.info("查询到的苹果订单信息为：{}",historyResponse);
            if(ObjectUtils.isNotEmpty(historyResponse)){
                revision = historyResponse.getRevision();
                hasMore = historyResponse.getHasMore();
                List<String> signedTransactions = historyResponse.getSignedTransactions();
                if(!CollectionUtils.isEmpty(signedTransactions)){
                    for(int i=0;i< signedTransactions.size();i++){
                        JWSTransactionDecodedPayload transactionDecodedPayload = sdv.verifyAndDecodeTransaction(historyResponse.getSignedTransactions().get(i));
                        log.info("验签解码后的数据为：{}",transactionDecodedPayload);
                        transactionDecodedPayloads.add(transactionDecodedPayload);
                    }
                }
            }
        } while(!StringUtils.isEmpty(revision) && hasMore);
        return transactionDecodedPayloads;
    }


    /**
     * @description ResponseBodyV2验证签名和解密
     * @author cwj
     * @param [responseBodyV2]
     * @return com.apple.itunes.storekit.model.ResponseBodyV2DecodedPayload
     * @date @time 2025/1/13 15:06
     **/
    public ResponseBodyV2DecodedPayload verifyAndDecodeNotification(ResponseBodyV2 responseBodyV2) {
        try{
            if(ObjectUtils.isEmpty(signedDataVerifier)){
                signedDataVerifier = createSignedDataVerifier();
            }
            return signedDataVerifier.verifyAndDecodeNotification(responseBodyV2.getSignedPayload());
        }catch (VerificationException e){
            log.error("验证签名和解密发生异常，异常原因为：{}",e.getMessage());
        }
       return null;
    }


    /**
     * @description JWSTransaction解密
     * @author cwj
     * @param [signedTransactionInfo]
     * @return com.iot08.apple.pay.model.JWSTransactionDecodedPayload
     * @date @time 2025/1/16 11:49
     **/
    public JWSTransactionDecodedPayload verifyAndDecodeTransaction(String signedTransactionInfo){
        try {
            if(ObjectUtils.isEmpty(signedDataVerifier)){
                signedDataVerifier = createSignedDataVerifier();
            }
            if(StringUtils.isNotEmpty(signedTransactionInfo)){
                return signedDataVerifier.verifyAndDecodeTransaction(signedTransactionInfo);
            }
            return null;
        } catch (VerificationException ae){
            log.error("查询订单信息出现异常，异常信息为：{}",ae.getMessage());
            return null;
        }
    }

    /**
     * @description JWSRenewalInfo解密
     * @author cwj
     * @param [signedRenewalInfo]
     * @return com.iot08.apple.pay.model.JWSRenewalInfoDecodedPayload
     * @date @time 2025/1/16 14:57
     **/
    public JWSRenewalInfoDecodedPayload verifyAndDecodeRenewalInfo(String signedRenewalInfo) {
        try {
            if(ObjectUtils.isEmpty(signedDataVerifier)){
                signedDataVerifier = createSignedDataVerifier();
            }
            if(StringUtils.isNotEmpty(signedRenewalInfo)){
                return signedDataVerifier.verifyAndDecodeRenewalInfo(signedRenewalInfo);
            }
            return null;
        } catch (VerificationException ae){
            log.error("查询订单信息出现异常，异常信息为：{}",ae.getMessage());
            return null;
        }
    }


    /**
     * @description 创建SignedDataVerifier对象
     * @author cwj
     * @param []
     * @return com.apple.itunes.storekit.verification.SignedDataVerifier
     * @date @time 2025/1/13 14:41
     **/
    public SignedDataVerifier createSignedDataVerifier() {
        return new SignedDataVerifier(rootAcs,bundleId,appAppleId,isSandEnv?Environment.SANDBOX:Environment.PRODUCTION,true);
    }

    /**
     * @description 创建制定环境的签名认证
     * @author cwj
     * @param [environment]
     * @return com.iot08.apple.pay.verification.SignedDataVerifier
     * @date @time 2025/2/5 9:40
     **/
    public SignedDataVerifier createSignedDataVerifier(boolean isSand) {
        return new SignedDataVerifier(rootAcs2,bundleId,appAppleId,isSand?Environment.SANDBOX:Environment.PRODUCTION,true);
    }

}
